/*******************************************************************************
 * Copyright (c) 2005, 2014 myspring.net
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 *******************************************************************************/
package net.myspring.common.utils;


import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import net.myspring.common.service.ServiceException;
import org.apache.commons.beanutils.PropertyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

public class Collections3 {
    private static Logger logger = LoggerFactory.getLogger(Collections3.class);

    public static <E> List<E> extractToList(final Collection collection, final String propertyName) {
        if (isEmpty(collection)) {
            return Lists.newArrayList();
        }
        List<E> list = new ArrayList(collection.size());
        try {
            for (Object obj : collection) {
                list.add((E) PropertyUtils.getProperty(obj, propertyName));
            }
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
        return list;
    }

    public static Set extractToSet(final Collection collection, final String propertyName) {
        if (isEmpty(collection)) {
            return Sets.newHashSet();
        }
        Set set = new LinkedHashSet();
        try {
            for (Object obj : collection) {
                set.add(PropertyUtils.getProperty(obj, propertyName));
            }
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
        return set;
    }

    public static <K, V> Map<K, V> extractToMap(final Collection collection, final String keyPropertyName) {
        if (isEmpty(collection)) {
            return Maps.<K, V>newHashMap();
        }
        Map<K, V> map = new HashMap<K, V>(collection.size());
        try {
            for (Object obj : collection) {
                map.put((K) PropertyUtils.getProperty(obj, keyPropertyName), (V) obj);
            }
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
        return map;
    }


    public static <P, C> List<P> join(List<P> parentList, List<C> childList, String parentKeyGetter, String parentChildGetter, String childKeyGetter) {
        Map<Object, Collection<C>> childMap = Maps.newHashMap();
        try {
            for (C item : childList) {
                Object key = item.getClass().getMethod(childKeyGetter).invoke(item);
                if (!childMap.containsKey(key)) {
                    childMap.put(key, Lists.<C>newArrayList());
                }
                childMap.get(key).add(item);
            }
            for (P item : parentList) {
                Object key = item.getClass().getMethod(parentKeyGetter).invoke(item);
                if (childMap.containsKey(key)) {
                    Collection<C> property = (Collection<C>) item.getClass().getMethod(parentChildGetter).invoke(item);
                    property.addAll(childMap.get(key));
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new ServiceException(e.getMessage());
        }
        return parentList;
    }


    public static boolean isEmpty(Collection collection) {
        return (collection == null) || collection.isEmpty();
    }

    public static boolean isEmpty(Map map) {
        return (map == null) || map.isEmpty();
    }

    public static boolean isNotEmpty(Collection collection) {
        return !isEmpty(collection);
    }

    public static boolean isNotEmpty(Map map) {
        return !isEmpty(map);
    }


}
